package fun.ticsmyc.rpc.server.transport.netty.handler;

import fun.ticsmyc.rpc.Config;
import fun.ticsmyc.rpc.common.entity.RpcRequest;
import fun.ticsmyc.rpc.common.entity.RpcResponse;
import fun.ticsmyc.rpc.server.handler.RpcRequestHandler;
import fun.ticsmyc.rpc.server.provider.ServiceProvider;
import fun.ticsmyc.rpc.server.provider.impl.DefaultServiceProvider;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Ticsmyc
 * @date 2020-10-23 20:48
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

    private ServiceProvider serviceProvider;

    public NettyServerHandler(){
        this.serviceProvider = Config.getServiceProvider();
    }

    public NettyServerHandler(ServiceProvider serviceProvider){
        this.serviceProvider = serviceProvider;
    }

    /**
     * 收到RpcRequest对象后触发。
     * 1. 根据RpcRequest调用相应方法， 获取结果
     * 2. 将响应结果写回Channel
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequest msg) throws Exception {
        if(msg.getHeartBeat()){
            logger.debug("收到客户端心跳");
            return;
        }
        logger.debug("服务器收到请求:{}",msg);
        Object obj = RpcRequestHandler.invokeMethod(serviceProvider, msg);
        RpcResponse<Object> success = RpcResponse.success(obj,msg.getRequestId());

        ctx.writeAndFlush(success);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("处理过程调用时发生异常");
        cause.printStackTrace();
        ctx.close();
    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent){
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if(idleStateEvent.state() == IdleState.READER_IDLE){
                logger.debug("10s未收到客户端消息，连接断开");
                ctx.close();
            }
        }else{
            super.userEventTriggered(ctx,evt);
        }
    }
}
